package com.ws.common.authentication;

import com.ws.entity.User;
import com.ws.service.UserService;
import com.ws.util.Result;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 授权
     * instanceof:严格来说是Java中的一个双目运算符，用来测试一个对象是否为一个类的实例
     * 当 obj 为 Class 的对象，或者是其直接或间接子类，或者是其接口的实现类，
     * 结果result 都返回 true，否则返回false。
     *大坑！，必须重写此方法，不然Shiro会报错
     * 根据token判断此Authenticator是否使用该realm
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如@RequiresRoles,@RequiresPermissions之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权~~~~~");
        String token = principalCollection.toString();
        String username=JWTUtil.getUsername(token);
        Result result = userService.getUserByName(username);
        User user = (User) result.getData();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //查询数据库来获取用户的角色
        info.addRole(user.getRoleName());
        //查询数据库来获取用户的权限
//        info.addStringPermission(user.getPermission());
        return info;
    }


    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("认证~~~~~~~");
        //getCredentials:获取用户信息
        String jwt = (String)authenticationToken.getCredentials();
        String username= null;
        //decode时候出错，可能是token的长度和规定好的不一样了
        try {
            username= JWTUtil.getUsername(jwt);
        }catch (Exception e){
            throw new AuthenticationException("token非法，不是规范的token，可能被篡改了，或者过期了");
        }
        if (!JWTUtil.verify(jwt)||username == null){
            throw new AuthenticationException("token认证失效，token错误或者过期，重新登陆");
        }
        Result result = userService.getUserByName(username);
        User user = (User) result.getData();
        if (user == null){
            throw new AuthenticationException("该用户不存在");
        }

        return new SimpleAuthenticationInfo(jwt, jwt,"MyRealm");
    }
}
